package net.blogways.ordermgr.common.command.dbquery;


import com.asiainfo.bpc.utils.ToolFactory;
import net.blogways.ordermgr.common.service.CommonService;
import net.blogways.ordermgr.entity.Datatable;
import net.blogways.ordermgr.util.Constants;
import net.blogways.ordermgr.util.DBTools;
import net.blogways.ordermgr.util.RescodeConstants;
import com.asiainfo.utils.Utils;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by chenfan on 2017/7/11.
 */
@Component("common:queryDataTable")
public class QueryDatableCommand implements Command {

  private final Logger log = LoggerFactory.getLogger(getClass());

  @Override
  public boolean execute(Context context) throws Exception {
    return Command.CONTINUE_PROCESSING;
  }

  /**
   * select datatable.
   *
   * @param context
   * @return
   * @throws Exception
   */
  public Boolean dataTable(Context context) throws Exception {
    if (sql_inj(context.toString())) {
      return Utils.returnFalseResult(context, RescodeConstants.ILLEGAL_CHARACTER, "非法参数");
    }
    String key = context.get("SEL_TABLE_SQL").toString();
    String sql = new String();
    if ("-1".equals(key)){
      sql = (String) context.get("SQL_STMT");
    } else {
      int index = key.indexOf("`");
      String tabName = key.substring(0, index);
      String sqlRef = key.substring(index + 1);
      log.debug(tabName);
      log.debug(sqlRef);
      String reg = ".*%.*%";

      if (sqlRef.matches(reg)) {
        sqlRef = sqlRef.replaceAll("%.*%", (String) context.get("params"));
      }
      Map<String, String> params = new HashMap<String, String>();
      params.put("tabName", tabName);
      params.put("sqlRef", sqlRef);
      log.debug("params= " + params);
      List rs = ToolFactory.getInstance().getSqlCodeService(Constants.DATABASE_CEN)
              .select("SELECT SQL_STMT FROM code_code WHERE tab_name= :tabName AND sql_ref = :sqlRef",
                      params);
      log.debug("rs=" + rs);
      if (rs.size() <= 0) {
        return Utils.returnFalseResult(context, "E401", "缺少查询语句");
      }
      sql = (String) ((Map) rs.get(0)).get("SQL_STMT");
    }


    String sqlCount = sql.replaceAll("(?i)^select[\\s\\S]*?from\\s+?", "select count(*) from ");
    log.debug("sql=" + sql);
    log.debug("sqlCount=" + sqlCount);
    Datatable table = new Datatable();
    Map sendData = table.datatable(sql, sqlCount, context);
    if (sendData.get("ERROR") != null && "0".equals(sendData.get("ERROR").toString())) {
      return Utils.returnFalseResult(context, RescodeConstants.ILLEGAL_CHARACTER, "非法参数");
    }
    log.debug("sendData=" + sendData);
    DBTools.checkBeforeEnd(context);
    return Utils.returnOk(context, sendData);
  }

  /**
   * 针对不确定数据库字段转义.
   *
   * @param context
   * @return
   * @throws Exception
   */
  public boolean dataTableFlow(Context context) throws Exception{

    log.debug("DataTableFlow begin:***************, context = {}", context);

    //国际化标识local
    String locale = "";
    if (null != context.get("locale")) {
      locale = (String) context.get("locale");
    } else {
      locale = "zh"; //默认中文
    }
    List resultList = (List) context.get("resultList");
    Map resultMap = (Map) resultList.get(0);
    List result = (List) resultMap.get("data");
    if (result.size() < 1){
      log.debug("result size < 1");
      log.debug("DataTableFlow end:***************, context = {}", context);
      return Utils.returnOkResult(context, "操作完成");
    }
    Map base;
    if (null == context.get("Base")){
      log.debug("context not contains Base");
      log.debug("DataTableFlow end:***************, context = {}", context);
      return Utils.returnOkResult(context, "操作完成");
    }

    base = (Map) context.get("Base");
    //RESV2存放不确定数据库字段转义
    if (null == base.get("RESV2")){
      log.debug("base not contains RESV2");
      log.debug("DataTableFlow end:***************, context = {}", context);
      return Utils.returnOkResult(context, "操作完成");
    }
    String dbRoute = base.get("DATASOURCE").toString();
    //ACCT_ID:TF_F_ACCOUNT;ACCT_ID:ACCT_NAME:name;locale|RATE_PLAN_ID:TD_B_RATEPLAN;RATEPLAN_ID:RATEPLAIN_DESRATEPLAIN_DES:RATEPLAN_NAME
    String code2NameStr = base.get("RESV2").toString();

    CommonService codeService = (CommonService) ToolFactory.getInstance().getContext()
            .getBean("commonService");

    String[] fields = code2NameStr.split("\\|");

    for (int j = 0; j < fields.length; j++){
      String temp = fields[j];
      if (temp.split(";").length < 3 ){ //无需传递locale
        locale = "";
      }
      String idTab = temp.split(";")[0]; //ACCT_ID:TF_F_ACCOUNT
      String tempName = temp.split(";")[1]; //ACCT_ID:ACCT_NAME:name
      for (int i = 0; i < result.size(); i++){
        Map map = (Map) result.get(i);
        if (null != map.get(idTab.split(":")[0])){
          String  cCode = map.get(idTab.split(":")[0]).toString();
          if (!cCode.equals("")){
            String code = tempName.split(":")[0] + ":" + cCode;
            Map nameMap = codeService
                    .getTypeNameByCode(idTab.split(":")[1], code , tempName.split(":")[1].toString() ,
                            locale, dbRoute);
            if (nameMap.size() > 0){
              if (tempName.split(":").length > 2){
                map.put(tempName.split(":")[2], nameMap.get(tempName.split(":")[1].toString()));
              } else {
                map.put(tempName.split(":")[1], nameMap.get(tempName.split(":")[1].toString()));
              }

            }

          }
        }

      }

    }

    log.debug("DataTableFlow end:***************, context = {}", context);
    return Utils.returnOkResult(context, "操作完成");
  }


  public static boolean sql_inj(String str){

    String inj_str = "$";

    String[] inj_stra=inj_str.split("\\|");

    for (int i=0 ; i < inj_stra.length ; i++ ){

      if (str.indexOf(inj_stra[i]) >= 0){

        return true;

      }

    }
    return false;

  }
}